package databook.util;

import java.util.HashMap;
import java.lang.reflect.Field;

import prefuse.util.ColorLib;

/**
 * Differs from prefuse color map in that it keys on strings and 
 * works in a static function so that any function can call it and
 * all color values can be centralized.  So that by populating
 * this map, the entire feel of the visualization can change
 * and be customizable.
 * 
 * Currently uses a hashmap, but I'm wondering if it's not faster and easier
 * to just have the static strings just be static ints with the value of the
 * color.  This would save a hashmap call and invoking it would save a function
 * call.  You just reference the field.  This was initially done this way to 
 * facilitate saving, but saving can still be done through reflection.  
 * 
 * Still saving time this way I guess
 * since we don't have to call ColorLib everytime we want a color.  
 * 
 * @author zach
 */
public class ColorMap {
    private static HashMap<String,Integer> map;
    private static int DEFAULT_COLOR;
    
    private static float stack_alpha = .65f;
    
    public static final String DEFAULT_NODE = "Default Node";
    public static final String DEFAULT_NODE_TEXT = "Default Node Text";
    public static final String UNSELECTED_NODE = "Unselected Node";
    public static final String SELECTED_NODE = "Selected Node";
    public static final String SELECTED_NODE_BORDER = "Selected Node Border";
    public static final String UNSELECTED_NODE_BORDER = "Unselected Node Border";
    public static final String SELECTED_SOURCE_NODE = "Selected Source Node";
    public static final String SELECTED_T_S_NODE = "Selected T S Node";
    public static final String SELECTED_TARGET_NODE = "Selected Target Node";
    public static final String DEFAULT_START_EDGE = "Default Start Edge";
    public static final String DEFAULT_END_EDGE = "Default End Edge";
    public static final String UNSELECTED_EDGE = "Unselected Edge";
    public static final String SELECTED_OUT_EDGE = "Selected Out Edge";
    public static final String SELECTED_IN_EDGE = "Selected In Edge";
    public static final String GENDER_F = "Gender F";
    public static final String GENDER_M = "Gender M";
    public static final String RACE_CAUCASIAN = "Race Cacucasian";
    public static final String RACE_ASIAN = "Race Asian";
    public static final String RACE_BLACK = "Race Black";
    public static final String RACE_AMERICAN_INDIAN = "Race American Indian";
    public static final String RACE_HISPANIC = "Race Hispanic";
    public static final String RACE_UNKNOWN = "Race Unknown";
    public static final String GRADUATED_Y = "Graduated Y";
    public static final String GRADUATED_N = "Graduated N";
    public static final String GRADUATED_NOT_YET = "Graduated Not Yet";
    
    /**
     * Set up all of the default colors.  Can get this from a file, or can
     * call a function that loads it from a string or something.
     */
    static {
        map = new HashMap<String,Integer>();
        DEFAULT_COLOR = ColorLib.gray(155);
        setColor(DEFAULT_NODE,ColorLib.rgb(190,190,255));
        setColor(DEFAULT_NODE_TEXT,ColorLib.gray(0));
        setColor(SELECTED_NODE,ColorLib.rgb(150,255,150));
        setColor(SELECTED_TARGET_NODE,ColorLib.rgb(255,150,150));
        setColor(SELECTED_SOURCE_NODE,ColorLib.rgb(255,255,150));
        setColor(SELECTED_T_S_NODE,ColorLib.rgb(255,190,130));
        setColor(UNSELECTED_NODE,ColorLib.rgb(190,190,255));
        setColor(SELECTED_NODE_BORDER,ColorLib.gray(0));
        setColor(UNSELECTED_NODE_BORDER,ColorLib.setAlpha(ColorLib.gray(255),255));
        
        setColor(DEFAULT_START_EDGE,ColorLib.setAlpha(ColorLib.hsb(.35f,.5f,.75f),10));
        setColor(DEFAULT_END_EDGE,ColorLib.setAlpha(ColorLib.hsb(.35f,1f,1f),255));
        setColor(SELECTED_OUT_EDGE,ColorLib.hsba(.5f,1f,1f,1));
        setColor(SELECTED_IN_EDGE,ColorLib.hsba(.75f,1f,1f,1));
        
        setColor(GENDER_M,ColorLib.rgba(.5f,.5f,1f,stack_alpha));
        setColor(GENDER_F,ColorLib.rgba(1f,.5f,.5f,stack_alpha));
        
        setColor(GRADUATED_Y,ColorLib.rgba(.3f,.9f,.3f,stack_alpha));
        setColor(GRADUATED_N,ColorLib.rgba(.9f,.3f,.3f,stack_alpha));
        setColor(GRADUATED_NOT_YET,ColorLib.rgba(.3f,.3f,.9f,stack_alpha));
        setColor(RACE_CAUCASIAN,ColorLib.rgba(.3f,.9f,.3f,stack_alpha));
        setColor(RACE_AMERICAN_INDIAN,ColorLib.rgba(.9f,.9f,.3f,stack_alpha));
        setColor(RACE_BLACK,ColorLib.rgba(.9f,.3f,.9f,stack_alpha));
        setColor(RACE_HISPANIC,ColorLib.rgba(0f,.6f,1f,stack_alpha));
        setColor(RACE_ASIAN,ColorLib.rgba(1f,.6f,0f,stack_alpha));
        setColor(RACE_UNKNOWN,ColorLib.rgba(.3f,.3f,.9f,stack_alpha));
    }
    
    public static void setColor(String key,int color) {
        map.put(key,new Integer(color));
    }
    
    public static int getColor(String key) {
        if (map.containsKey(key)) {
            return map.get(key).intValue();
        } else {
            return DEFAULT_COLOR;
        }
    }
    
    public static int getColorFromProperty(String key) {
        try {
            Field field = ColorMap.class.getField(propertify(key));
            return getColor((String)field.get(new ColorMap()));
        } catch (NoSuchFieldException nsfe) {
            return DEFAULT_COLOR;
        } catch (IllegalAccessException iae) {
            return DEFAULT_COLOR;
        }
    }
    
    public static String propertify(String prop) {
        return prop.replaceAll(" ","_").toUpperCase();
    }
}
